<!DOCTYPE html>
<html lang='en'>

<head>
  <meta charset="utf-8">
  <link href="/css/phylotree.css" rel="stylesheet">

  <link rel="stylesheet" href="/css/bootstrap.min.css">
  <link rel="stylesheet" href="/css/bootstrap-theme.min.css">

  <script src="/js/jquery.js"></script>
  <script src="/js/bootstrap.min.js"></script>
  <script src="/js/d3.v3.min.js"></script>
  <script src="/js/underscore-min.js"></script>
  <script src="/phylotree.min.js"></script>

  <style>
    .bootstrap {
      font-size: 12px;
      background-fill: #cccccc;
    }

    .cluster-text {
      padding: 0.25em;
      text-align: center;
    }


    @media print {
      .no-print,
      .no-print * {
        display: none !important;
      }
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="row no-print">
      <div class="col-md-6">

        <div>
          <form>
            <label>Radial layout </label>
            <input type="checkbox" id="layout" />
            <button type="button" class="btn btn-sm" data-toggle="modal" data-target="#newick_modal">Input Newick</button>
            <button type="button" class="btn btn-sm" data-toggle="modal" data-target="#clustering_modal">Input clustering</button>
          </form>
        </div>

      </div>
    </div>

    <div class="row">
      <div class="col-md-12" id="tree-container">
        <svg id="tree_display"></svg>
      </div>
    </div>

    <div class="row">
      <div class="col-md-2" id="cluster-legend">
      </div>
    </div>

    <div class="modal" id='newick_modal'>
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            <h4 class="modal-title">Newick string to render</h4>
          </div>
          <div class="modal-body" id='newick_body'>
            <textarea id='nwk_spec' autofocus=t rue placeholder="" style='width: 100%; height: 100%' rows=2 0 selectionStart=1 selectionEnd=1 000>(a : 0.1, (b : 0.11, (c : 0.12, d : 0.13) : 0.14) : 0.15)</textarea>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-primary" id='validate_newick'>Display this tree</button>
          </div>
        </div>
        <!-- /.modal-content -->
      </div>
      <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->

    <div class="modal" id='clustering_modal'>
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            <h4 class="modal-title">Clustering CSV</h4>
          </div>
          <div class="modal-body" id='clustering_body'>
            <textarea id='csv_spec' autofocus=t rue placeholder="" style='width: 100%; height: 100%' rows=2 0 selectionStart=1 selectionEnd=1 000>
Seq1,Seq2,Seq3
A,B,A
             </textarea>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-primary" id='validate_csv'>Use this labeling</button>
          </div>
        </div>
        <!-- /.modal-content -->
      </div>
      <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->

    <script>
      // the global tree variable
      var tree;

      // the dictionary mapping node names to clusters
      var clustering = {};

      // default scheme to color by date    
      var coloring_scheme = d3.scale.category10();

      // this will be used to map bootstrap support values to edge thickness
      var bootstrap_scale = d3.scale.linear().domain([0, 0.5, 0.7, 0.9, 0.95, 1]).range([1, 2, 3, 4, 5, 6]).interpolate(d3.interpolateRound);

      function edgeStyler(dom_element, edge_object) {
        if ("bootstrap" in edge_object.target) {
          dom_element.style("stroke-width", bootstrap_scale(edge_object.target.bootstrap) + "pt");
        }
        dom_element.style("stroke", "cluster" in edge_object.target ? coloring_scheme(edge_object.target.cluster) : null);

      }

      function nodeStyler(dom_element, node_object) {
        if ("bootstrap" in node_object && node_object.bootstrap) {
          var label = dom_element.selectAll(".bootstrap");
          if (label.empty()) {            
            dom_element.append("text").classed("bootstrap", true).text(node_object.bootstrap).attr("dx", ".3em").attr("text-anchor", "start").attr("alignment-baseline", "middle");
          } else {
            if (tree.radial()) { // do not show internal node labels in radial mode
              label.remove();
            }
          }
        }
      }

      function drawATree(newick) {

        tree = d3.layout.phylotree()
          .svg(d3.select("#tree_display"))
          .options({
            'selectable': false,
            // make nodes and branches not selectable
            'collapsible': false,
            // turn off the menu on internal nodes
          })
          .style_edges(edgeStyler)
          .style_nodes(nodeStyler)
          .node_circle_size(0) // do not draw clickable circles for internal nodes
        ;


        /* the next call creates the tree object, and tree nodes */
        tree(d3.layout.newick_parser(newick));


        // parse bootstrap support from internal node names
        _.each(tree.get_nodes(), function(node) {
          if (node.children) {
            node.bootstrap = parseFloat(node.name);
          }
        });

        tree.spacing_x(25).spacing_y(100);

        if ($("#layout").prop("checked")) {
          tree.radial(true);
        }
        tree.placenodes().layout();


        // UI handlers
        $("#layout").on("click", function(e) {
          tree.radial($(this).prop("checked")).placenodes().update();
        });
      }

      function loadTreeFromURL(url) {
        d3.text(url, function(error, newick) {
          drawATree(newick);
          loadAnnotationFromURL("annotation.csv");
        });
      }

      function applyAnnotation(clustering) {
        coloring_scheme.domain([]); // reset the coloring scheme
        if (tree) {
          // refresh cluster assignments for tips
          /*_.each (tree.get_nodes(), function (node) {
              if (node.name in clustering) {
                  node.cluster = clustering[node.name];
              } else {
                  delete node.cluster;
              }
          });*/

          tree.traverse_and_compute(function(node) {
              if (node.name in clustering) {
                node.cluster = clustering[node.name];
              } else {
                delete node.cluster;
                var children_clusters = _.keys(_.countBy(node.children, function(d) {
                  return d.cluster;
                }));
                if (children_clusters.length == 1 && children_clusters[0]) {
                  node.cluster = children_clusters[0];
                }
              }
            },
            "post-order");



          tree.update();

          // update the legend

          d3.select("#cluster-legend").selectAll(".row").remove();
          var cluster_colors = d3.select("#cluster-legend").selectAll(".row").data(coloring_scheme.domain().sort().map(function(d) {
            return [d];
          }));
          cluster_colors.enter().append("div").classed("row", true);
          cluster_colors.exit().remove();
          cluster_colors = cluster_colors.selectAll("span").data(function(d) {
            return d
          });
          cluster_colors.enter().append("span").classed("cluster-text", true);

          cluster_colors.each(function(d) {
            d3.select(this).style("color", coloring_scheme(d), "important").classed("cluster-text", true).text("Cluster " + d);
          });

        }
      }

      function loadAnnotationFromURL(url) {
        d3.csv(url, function(error, csv) {
          applyAnnotation(csv[0]);
        });
      };

      $("#validate_newick").on("click", function(e) {
        var res = d3_phylotree_newick_parser($('textarea[id$="nwk_spec"]').val(), true);
        if (res["error"] || !res["json"]) {
          var warning_div = d3.select("#newick_body").selectAll("div  .alert-danger").data([res["error"]])
          warning_div.enter().append("div");
          warning_div.html(function(d) {
            return d;
          }).attr("class", "alert-danger");

        } else {
          drawATree($('textarea[id$="nwk_spec"]').val());
          $('#newick_modal').modal('hide');
        }
      });

      $("#validate_csv").on("click", function(e) {
        var res = d3.csv.parse($('textarea[id$="csv_spec"]').val());
        if (!res) {
          var warning_div = d3.select("#clustering_body").selectAll("div  .alert-danger").data("Failed to parse CSV")
          warning_div.enter().append("div");
          warning_div.html(function(d) {
            return d;
          }).attr("class", "alert-danger");

        } else {

          applyAnnotation(res[0]);
          $('#clustering_modal').modal('hide');
        }
      });

      loadTreeFromURL("tree.nwk");
    </script>

</body>

</html>
